package com.yihaodian.search.fetch;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.DocumentStoredFieldVisitor;
import org.apache.lucene.index.StoredFieldVisitor;

import com.yihaodian.api.search.SearchException;
import com.yihaodian.api.search.misc.SearchHit;
import com.yihaodian.search.SearchContext;
import com.yihaodian.search.SearchPhase;

public class FetchPhase implements SearchPhase {

	@Override
	public void execute(SearchContext context) throws SearchException {
		/**
		 * TODO More efficent way to fetch docs.
		 * 1. Wrap the fields in byte[].
		 *    [Improve] Lucene4.0 FieldsVisitor: Load fields and return source by byte[].
		 * 2. Highlight、Grouping and other phases integration.
		 */
		int[] docIdsToLoad = context.getDocIdsToLoad();
		SearchHit[] hits = new SearchHit[docIdsToLoad.length];
		DocumentStoredFieldVisitor fieldVistor = new DocumentStoredFieldVisitor(
				context.getShardRequest().getSearchRequest().getFields());
		for (int i = 0; i < docIdsToLoad.length; i++) {
			doc(context, fieldVistor, docIdsToLoad[i]);
			SearchHit hit = new SearchHit();
			hit.setDocId(docIdsToLoad[i]);
			hit.setFieldValues(getField(context, fieldVistor.getDocument()));
//			hit.setScore(score);
			hits[i] = hit;
		}
		
		FetchSearchResult fetchResult = new FetchSearchResult();
		fetchResult.setHits(hits);
		context.setFetchResult(fetchResult);
	}
	
	private void doc(SearchContext context, StoredFieldVisitor visitor, int docId)
		throws SearchException{
		try {
			context.getSearcher().searcher().doc(docId, visitor);
		} catch (Exception e) {
			throw new SearchException(e);
		}
	}
	
	private Map<String, String> getField(SearchContext context, Document doc){
		Map<String, String> fields = new HashMap<String, String>();
		Set<String> fieldName = context.getShardRequest().getSearchRequest().getFields();
		Iterator<String> it = fieldName.iterator();
		while (it.hasNext()) {
			String field = it.next();
			fields.put(field, doc.get(field));// doc.getBinaryValue(name);
		}
		
		return fields;
	}

}
